﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;

namespace UBCon.Ribbon
{
    using UBCon.Core.Enums;
    using UBCon.Ribbon.BaseControls;
    using UBCon.Ribbon.Interfaces;
    using UBCon.Ribbon.Models;
    using System.Windows.Documents;
    using System.Windows.Shapes;
    using System.Windows.Media;

    [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)]
    [StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(RibbonGroup))]
    [TemplatePart(Name = rootControlName, Type = typeof(FrameworkElement))]
    public class RibbonTabItem : HeaderedItemsControl, IRibbonControl
    {
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------
        #region Constructors

        /// <summary>
        /// Default static constructor.
        /// </summary>
        static RibbonTabItem()
        {
            Type ownerType = typeof(RibbonTabItem);
            RibbonTabItem.DefaultStyleKeyProperty.OverrideMetadata(ownerType,
                new System.Windows.FrameworkPropertyMetadata(ownerType));
            RibbonTabItem.VisibilityProperty.OverrideMetadata(ownerType, new FrameworkPropertyMetadata(Visibility.Visible));

        }

        /// <summary>
        /// Initializes a new instance of UBCon.Ribbon.RibbonTabItem class.
        /// </summary>
        public RibbonTabItem()
            : base()
        {
        }


        #endregion

        //------------------------------------------------------
        //
        //  Properties
        //
        //------------------------------------------------------
        #region Properties
        
        //public bool ShowContextual
        //{
        //    get { return (bool)GetValue(ShowContextualProperty); }
        //    set { SetValue(ShowContextualProperty, value); }
        //}

        //// Using a DependencyProperty as the backing store for ShowContextual.  This enables animation, styling, binding, etc...
        //public static readonly DependencyProperty ShowContextualProperty =
        //    DependencyProperty.Register("ShowContextual", typeof(bool), typeof(RibbonTabItem), 
        //    new PropertyMetadata(false, OnShowContextualChanged));

        //private static void OnShowContextualChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        //{
            
        //    RibbonTabItem item = sender as RibbonTabItem;
        //    bool newValue = (bool)e.NewValue, oldValue = !newValue;
        //    if (newValue)
        //    {
        //        if (item._contextHeader == null)
        //        {
        //            item._contextHeader = new Button()
        //            {
        //                Width = 15,
        //                Height = 15,
        //                Background = Brushes.Black,
        //                Visibility = Visibility.Collapsed,
        //                Margin=new Thickness(0,-55,0,0),
        //                Content="Plz, say hello to the world!!"
        //            };
        //        }
        //        Panel.SetZIndex(item._contextHeader, 100);
        //        item._contextHeader.Visibility = Visibility.Visible;
        //    }
        //    else
        //    {
        //        if (item._contextHeader != null)
        //        {
        //            item._contextHeader.Visibility = Visibility.Collapsed;
        //        }
        //    }
        //}

        /// <summary>
        /// Gets ItemsControl which owns this control.
        /// </summary>
        internal RibbonBar LogicalParent
        {
            get
            {
                return ItemsControl.ItemsControlFromItemContainer(this) as RibbonBar;
            }
        }

        internal ContextualTabItemsGroup ContextualTabItemsGroup
        {
            get { return (ContextualTabItemsGroup)GetValue(ContextualTabItemsGroupProperty); }
            set { SetValue(ContextualTabItemsGroupProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ContextualTabItemsGroup.  This enables animation, styling, binding, etc...
        internal static readonly DependencyProperty ContextualTabItemsGroupProperty =
            DependencyProperty.Register("ContextualTabItemsGroup", typeof(ContextualTabItemsGroup), typeof(RibbonTabItem), new PropertyMetadata(null));

        /// <summary>
        /// Gets a boolean value indicating whether UBCon.Ribbon.RibbonTabItem is contextual.
        /// </summary>
        public bool IsContextual
        {
            get { return (bool)GetValue(IsContextualProperty); }
        }

        // Using a DependencyProperty as the backing store for IsContextual.  This enables animation, styling, binding, etc...
        internal static readonly DependencyPropertyKey IsContextualPropertyKey =
            DependencyProperty.RegisterReadOnly("IsContextual", typeof(bool), typeof(RibbonTabItem), 
            new FrameworkPropertyMetadata(false));

        /// <summary>
        /// Identifies UBCon.Ribbon.RibbonTabItem.IsContextual dependency property.
        /// </summary>
        internal static readonly DependencyProperty IsContextualProperty = RibbonTabItem.IsContextualPropertyKey.DependencyProperty;

        /// <summary>
        /// Gets or sets a boolean value indicating whether UBCon.Ribbon.RibbonTabItem is selected.
        /// This is a dependency property.
        /// </summary>
        [Browsable(true)]
        [Bindable(true)]
        [Category("Behaviour")]
        public bool IsSelected
        {
            get { return (bool)GetValue(IsSelectedProperty);}
            set { SetValue(IsSelectedProperty, value); }
        }

        /// <summary>
        /// Identifies UBCon.Ribbon.RibbonTabItem.IsSelected dependency property.
        /// </summary>
        public static readonly DependencyProperty IsSelectedProperty = SelectorBase.IsSelectedProperty.AddOwner(typeof(RibbonTabItem));

        #endregion

        //------------------------------------------------------
        //
        //  Depenency Property Changed Callbacks
        //
        //------------------------------------------------------
        #region Depenency Property Changed Callbacks

        ///// <summary>
        ///// Invoked when Visibility property changes.
        ///// </summary>
        ///// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        ///// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        //private static void OnVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        //{
        //    //RibbonTabItem tabItem = (RibbonTabItem)d;
        //    //if (tabItem.IsContextual &&
        //    //            tabItem.ContextualTabItemsGroup != null)
        //    //{
        //    //    if (tabItem.ContextualTabItemsGroup.Items.IndexOf(tabItem) != 0)
        //    //    {
        //    //        return;
        //    //    }
        //    //    if ((Visibility)e.NewValue == Visibility.Visible)
        //    //    {
        //    //        tabItem.ContextualTabItemsGroup.NotifyOnChildVisibilityChanged(tabItem);
        //    //    }
        //    //    else
        //    //    {
        //    //        tabItem.ContextualTabItemsGroup.NotifyOnChildVisibilityCollapsed(tabItem);
        //    //    }
        //    //}
        //}

        ///// <summary>
        ///// Coerces Visibility property.
        ///// </summary>
        ///// <param name="sender">Type: System.Windows.DependencyObject. The object that the property exists on. When the callback is invoked, the property system will pass this value.</param>
        ///// <param name="value">Type: System.Object. The new value of the property, prior to any coercion attempt.</param>
        ///// <returns>Type: System.Object. The coerced value (with appropriate type). </returns>
        //private static object CoerceVisibility(DependencyObject sender, object value) 
        //{
        //    RibbonTabItem tabItem = sender as RibbonTabItem;

        //    if (tabItem.IsContextual) 
        //    {
        //        Visibility visibility = (Visibility)value;

        //        if (visibility == Visibility.Visible &&
        //            !tabItem.IsMeasureValid &&
        //            tabItem.ContextualTabItemsGroup != null &&
        //            tabItem.ContextualTabItemsGroup.Items.IndexOf(tabItem) == 0)
        //        {
        //            ItemsControl iControl = ItemsControl.ItemsControlFromItemContainer(tabItem);
        //            tabItem.LayoutUpdated += tabItem.OnLayoutUpdated;
        //        }            
        //    }

        //    return value;
        //}

        //private static void OnMeasuredWidthPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        //{
        //    //RibbonTabItem item = (RibbonTabItem)d;
        //    //if (item.IsContextual && item.ContextualTabItemsGroup != null)
        //    //{
        //    //    BindingExpression exp = item.ContextualTabItemsGroup.GetBindingExpression(ContextualTabItemsGroup.WidthProperty);
        //    //    if (exp != null)
        //    //    {
        //    //        exp.UpdateTarget();
        //    //        item.ContextualTabItemsGroup.ExtraWidth = item.ContextualTabItemsGroup.Width;
        //    //    }
        //    //}
        //}

        #endregion

        //------------------------------------------------------
        //
        //  Overrides
        //
        //------------------------------------------------------
        #region Overrieds

        /// <summary>
        /// Invoked when control's render size changes.
        /// </summary>
        /// <param name="sizeInfo">Type: System.Windows.SizeChangedInfo. Report the specifics of the value 
        /// change involving a System.Windwos.Size.</param>
        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            base.OnRenderSizeChanged(sizeInfo);
            RibbonTabItemModel model = GetValue(RibbonTabItemPanel.RibbonTabItemModelProperty) as RibbonTabItemModel;
            if (model != null) 
            {
                model.UpdateParentsWidth();
            }
        }

        /// <summary>
        /// Invoked whenever application code or internal processes (such as a rebuilding layout pass) call ApplyTemplate. 
        /// In simplest terms, this means the method is called just before a UI element displays in  app.  
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            if (rootContol != null)
            {
                rootContol.MouseLeftButtonDown -= OnRootControlPressed;
            }

            rootContol = GetTemplateChild(rootControlName) as FrameworkElement;

            if (rootContol != null)
            {
                rootContol.MouseLeftButtonDown += OnRootControlPressed;
                //if (rootContol is Panel && _contextHeader != null)
                //{
                //    (rootContol as Panel).Children.Add(_contextHeader);
                //}
            }
        }

        #endregion

        //------------------------------------------------------
        //
        //  Public Methods
        //
        //------------------------------------------------------
        #region Public Methods
        #endregion

        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------
        #region Internal Methods
        #endregion

        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------
        #region  Private Methods
        #endregion

        //------------------------------------------------------
        //
        //  Event Handlers
        //
        //------------------------------------------------------
        #region Event Handlers

        /// <summary>
        /// Invoked when header part of the control is pressed.
        /// </summary>
        /// <param name="sender">Owner of the event.</param>
        /// <param name="e">Event data for the event which provides data for mouse button released events.</param>
        private void OnRootControlPressed(object sender, MouseButtonEventArgs e)
        {
            if (LogicalParent != null)
            {
                int index = LogicalParent.ItemContainerGenerator.IndexFromContainer(this);
                if (e.ClickCount == 1)
                {
                    if (LogicalParent.IsValidIndex(index) && LogicalParent.SelectedIndex != index)
                    {
                        if (LogicalParent.SelectedIndex >= 0)
                        {
                            DependencyObject pItem = LogicalParent.ItemContainerGenerator.ContainerFromItem(LogicalParent.Items[LogicalParent.SelectedIndex]);
                            if (pItem != null)
                            {
                                pItem.ClearValue(RibbonTabItem.IsSelectedProperty);
                            }
                        }

                        LogicalParent.SetValue(RibbonBar.SelectedIndexProperty, index);

                        if (LogicalParent.Mode == Core.Enums.RibbonBarMode.ShowOnlyTabs && 
                            !LogicalParent.IsDropDownOpen)
                        {
                            LogicalParent.IsDropDownOpen = true;
                        }
                    }
                }
                
                else if (e.ClickCount == 2)
                {
                    RibbonBarMode mode = LogicalParent.Mode == RibbonBarMode.ShowOnlyTabs ? RibbonBarMode.ShowTabsAndCommands : RibbonBarMode.ShowOnlyTabs;
                    LogicalParent.SetValue(RibbonBar.ModeProperty, mode);
                }
            }
        }

        #endregion

        //------------------------------------------------------
        //
        //  Fields
        //
        //------------------------------------------------------
        #region Fields

        private FrameworkElement rootContol;
        private const string rootControlName = "PART_TabItemToot";
        //private Button _contextHeader;
        #endregion

        //------------------------------------------------------
        //
        //  IRibbonControl Implementation
        //
        //------------------------------------------------------
        #region IRibbonControl Implementation

        /// <summary>
        /// Gets a boolean value indicating whether the contol's size is large
        /// </summary>
        public bool IsLarge
        {
            get { return true; }
        }

        #endregion

        //------------------------------------------------------
        //
        //  Events
        //
        //------------------------------------------------------
        #region Events

        internal static readonly RoutedEvent AddToParentEvent = EventManager.RegisterRoutedEvent
           (
           "AddToParent",
            RoutingStrategy.Bubble,
            typeof(RoutedEventHandler),
            typeof(RibbonTabItem)
           );

        /// <summary>
        /// 
        /// </summary>
        [Category("Behavior")]
        internal event RoutedEventHandler AddToParent
        {
            add { this.AddHandler(AddToParentEvent, value); }
            remove { this.RemoveHandler(AddToParentEvent, value); }
        }

        #endregion

    }
}
